package com.mls.fivedistrict.util;

import org.joda.time.DateTime;
import org.joda.time.Duration;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Created by chenxiuxiang on 2018/3/24.
 */
public class TimeUtils {

    private static final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    public static final DateFormat DOT_FORMAT = new SimpleDateFormat("yyyy.MM.dd", Locale.getDefault());
    public static final DateFormat FORMAT = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());

    /**
     * 获取今天还剩多少毫秒
     *
     * @return
     */
    public static long getNowMistiming() {
        DateTime dateTime = new DateTime().millisOfDay().withMaximumValue();
        long millSeconds2 = new Duration(new DateTime(), dateTime).getMillis();
        return millSeconds2;
    }

    /**
     * 获取指定日期距离当前的毫秒
     *
     * @param date
     * @return
     */
    public static long getAssignDayMistiming(Date date) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String str = format.format(date);
        try {
            Date d2 = format.parse(str);
            long curMillisecond = d2.getTime();//当天的毫秒
            int dayMis = 1000 * 60 * 60 * 24;//一天的毫秒-1
            return curMillisecond + (dayMis - 1) - date.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 判断选择的日期是否是今天
     */
    public static boolean isToday(long time) {
        return isThisTime(time, "yyyy-MM-dd");
    }

    //判断选择的日期是否是本月
    public static boolean isThisMonth(long time) {
        return isThisTime(time, "yyyy-MM");
    }

    private static boolean isThisTime(long time, String pattern) {
        Date date = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String param = sdf.format(date);//参数时间
        String now = sdf.format(new Date());//当前时间
        if (param.equals(now)) {
            return true;
        }
        return false;
    }

    /**
     * 将时间戳转为Date类型
     *
     * @param millis 毫秒时间戳
     * @return Date类型时间
     */
    public static Date millis2Date(final long millis) {
        return new Date(millis);
    }

    /**
     * 获取两个时间差（单位：unit）
     *
     * @param date0 Date类型时间0
     * @param date1 Date类型时间1
     * @param unit  单位类型
     *              <ul>
     *              <li>{@link TimeConstants#MSEC}: 毫秒</li>
     *              <li>{@link TimeConstants#SEC }: 秒</li>
     *              <li>{@link TimeConstants#MIN }: 分</li>
     *              <li>{@link TimeConstants#HOUR}: 小时</li>
     *              <li>{@link TimeConstants#DAY }: 天</li>
     *              </ul>
     * @return unit时间戳
     */
    public static long getTimeSpan(final Date date0, final Date date1, final int unit) {
        return millis2TimeSpan(Math.abs(date2Millis(date0) - date2Millis(date1)), unit);
    }

    /**
     * 获取两个时间差（单位：unit）
     *
     * @param millis0 毫秒时间戳0
     * @param millis1 毫秒时间戳1
     * @param unit    单位类型
     *                <ul>
     *                <li>{@link TimeConstants#MSEC}: 毫秒</li>
     *                <li>{@link TimeConstants#SEC }: 秒</li>
     *                <li>{@link TimeConstants#MIN }: 分</li>
     *                <li>{@link TimeConstants#HOUR}: 小时</li>
     *                <li>{@link TimeConstants#DAY }: 天</li>
     *                </ul>
     * @return unit时间戳
     */
    public static long getTimeSpan(final long millis0, final long millis1, final int unit) {
        return millis2TimeSpan(Math.abs(millis0 - millis1), unit);
    }

    /**
     * 获取合适型两个时间差
     *
     * @param date0     Date类型时间0
     * @param date1     Date类型时间1
     * @param precision 精度
     *                  <p>precision = 0，返回null</p>
     *                  <p>precision = 1，返回天</p>
     *                  <p>precision = 2，返回天和小时</p>
     *                  <p>precision = 3，返回天、小时和分钟</p>
     *                  <p>precision = 4，返回天、小时、分钟和秒</p>
     *                  <p>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</p>
     * @return 合适型两个时间差
     */
    public static String getFitTimeSpan(final Date date0, final Date date1, final int precision) {
        return millis2FitTimeSpan(Math.abs(date2Millis(date0) - date2Millis(date1)), precision);
    }

    /**
     * 将Date类型转为时间戳
     *
     * @param date Date类型时间
     * @return 毫秒时间戳
     */
    public static long date2Millis(final Date date) {
        return date.getTime();
    }

    private static long timeSpan2Millis(final long timeSpan, final int unit) {
        return timeSpan * unit;
    }

    private static long millis2TimeSpan(final long millis, final int unit) {
        return millis / unit;
    }

    private static String millis2FitTimeSpan(long millis, int precision) {
        if (millis < 0 || precision <= 0) return null;
        precision = Math.min(precision, 5);
        String[] units = {"天", "小时", "分钟", "秒", "毫秒"};
        if (millis == 0) return 0 + units[precision - 1];
        StringBuilder sb = new StringBuilder();
        int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
        for (int i = 0; i < precision; i++) {
            if (millis >= unitLen[i]) {
                long mode = millis / unitLen[i];
                millis -= mode * unitLen[i];
                sb.append(mode).append(units[i]);
            }
        }
        return sb.toString();
    }

    /**
     * 获取指定日期的后一天
     *
     * @param date
     * @return
     */
    public static Date getAfterDays(Date date) {
        Calendar cld = Calendar.getInstance();
        cld.setTime(date);
        cld.add(Calendar.DATE, 1);
        Date afterDays = cld.getTime();
        //获得下一天日期字符串
        return afterDays;

    }

    /**
     * 将日期转换成 yyyy-dd-dd
     *
     * @param date
     * @return
     */
    public static Date date2D(Date date) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String formatStr = format.format(date);
        System.out.println("formatStr:" + formatStr);
        Date parse = null;
        try {
            parse = format.parse(formatStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;

    }

    /**
     * 将时间字符串转为时间戳
     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>
     *
     * @param time 时间字符串
     * @return 毫秒时间戳
     */
    public static long string2Millis(final String time) {
        return string2Millis(time, DEFAULT_FORMAT);
    }

    /**
     * 将时间字符串转为时间戳
     * <p>time格式为format</p>
     *
     * @param time   时间字符串
     * @param format 时间格式
     * @return 毫秒时间戳
     */
    public static long string2Millis(final String time, final DateFormat format) {
        try {
            return format.parse(time).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return -1;
    }


    /**
     * 获取指定日期距离24点有多少毫秒
     *
     * @param date
     * @return
     */
    public static long date24Time(Date date) {
        long lastTime = date.getTime();
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String formatStr = format.format(date);
        String formatDateStr = format.format(date);
        String nowDateStr = formatDateStr + " 23:59:59";
        long nowTime = string2Millis(nowDateStr);
        return nowTime - lastTime;

    }

    /**
     * 获取指定日期当天的毫秒值
     *
     * @param date
     * @return
     */
    public static long date24(Date date) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String formatDateStr = format.format(date);
        String nowDateStr = formatDateStr + " 23:59:59";
        long nowTime = string2Millis(nowDateStr);
        return nowTime;

    }

    public static String millis2Hour(final long millis) {
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");//初始化Formatter的转换格式。
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        String hms = formatter.format(millis);
        return hms;
    }

    /**
     * 获取与当前时间的差（单位：unit）
     *
     * @param date Date类型时间
     * @param unit 单位类型
     *             <ul>
     *             <li>{@link TimeConstants#MSEC}: 毫秒</li>
     *             <li>{@link TimeConstants#SEC }: 秒</li>
     *             <li>{@link TimeConstants#MIN }: 分</li>
     *             <li>{@link TimeConstants#HOUR}: 小时</li>
     *             <li>{@link TimeConstants#DAY }: 天</li>
     *             </ul>
     * @return unit时间戳
     */
    public static long getTimeSpanByNow(final Date date, final int unit) {
        return getTimeSpan(new Date(), date, unit);
    }

    /**
     * 获取与当前时间的差（单位：unit）
     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>
     *
     * @param time 时间字符串
     * @param unit 单位类型
     *             <ul>
     *             <li>{@link TimeConstants#MSEC}: 毫秒</li>
     *             <li>{@link TimeConstants#SEC }: 秒</li>
     *             <li>{@link TimeConstants#MIN }: 分</li>
     *             <li>{@link TimeConstants#HOUR}: 小时</li>
     *             <li>{@link TimeConstants#DAY }: 天</li>
     *             </ul>
     * @return unit时间戳
     */
    public static long getTimeSpanByNow(final String time, final int unit) {
        return getTimeSpan(getNowString(), time, DEFAULT_FORMAT, unit);
    }

    /**
     * 获取两个时间差（单位：unit）
     * <p>time0和time1格式都为format</p>
     *
     * @param time0  时间字符串0
     * @param time1  时间字符串1
     * @param format 时间格式
     * @param unit   单位类型
     *               <ul>
     *               <li>{@link TimeConstants#MSEC}: 毫秒</li>
     *               <li>{@link TimeConstants#SEC }: 秒</li>
     *               <li>{@link TimeConstants#MIN }: 分</li>
     *               <li>{@link TimeConstants#HOUR}: 小时</li>
     *               <li>{@link TimeConstants#DAY }: 天</li>
     *               </ul>
     * @return unit时间戳
     */
    public static long getTimeSpan(final String time0, final String time1, final DateFormat format, final int unit) {
        return millis2TimeSpan(Math.abs(string2Millis(time0, format) - string2Millis(time1, format)), unit);
    }


    /**
     * 获取当前时间字符串
     * <p>格式为format</p>
     *
     * @param format 时间格式
     * @return 时间字符串
     */
    public static String getNowString(final DateFormat format) {
        return millis2String(System.currentTimeMillis(), format);
    }

    /**
     * 获取当前时间字符串
     * <p>格式为yyyy-MM-dd HH:mm:ss</p>
     *
     * @return 时间字符串
     */
    public static String getNowString() {
        return millis2String(System.currentTimeMillis(), DEFAULT_FORMAT);
    }

    /**
     * 将时间戳转为时间字符串
     * <p>格式为format</p>
     *
     * @param millis 毫秒时间戳
     * @param format 时间格式
     * @return 时间字符串
     */
    public static String millis2String(final long millis, final DateFormat format) {
        return format.format(new Date(millis));
    }


    public static void main(String[] args) {
        long timeSpanByNow = TimeUtils.getTimeSpanByNow("2018-04-08 00:00:00", TimeConstants.SEC);
        System.out.println("差值" + (timeSpanByNow < 30 * 24 * 60 * 60));
//        Date date = new Date(1522857600000L);
//        date2D(date);
//        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//        try {
//            Date parse = format.parse("2018-3-28 15:17");
//            long assignDayMistiming = getAssignDayMistiming(parse);
//            System.out.println("assignDayMistiming:" + assignDayMistiming);
//            long nowMistiming = getNowMistiming();
//            System.out.println("nowMistiming:" + nowMistiming);
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
    }


}
